package org.mwielocha.jxcube.ut;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;


public class SimpleScaleBar extends PropertyHelper implements PaintListener, MouseListener, MouseMoveListener {
  
  protected Composite composite, parent;
  
  private int minValue = 0, maxValue = 100;
  private double selection = 0;
  
  private Color fillColor, outlineColor;
  
  private int topMargin, bottomMargin;
  
  private boolean mousePressed;
  
  private Set<MouseListener> mouseListeners;
  
  public SimpleScaleBar(Composite parent, int topMargin, int bottomMargin) {
    this.parent = parent;
    this.topMargin = topMargin;
    this.bottomMargin = bottomMargin;
    mouseListeners = new HashSet<MouseListener>();
    fillColor = ColorUtil.toSWTColor(parent.getDisplay(), java.awt.Color.LIGHT_GRAY);
    outlineColor = ColorUtil.toSWTColor(parent.getDisplay(), java.awt.Color.GRAY);
    createControl();
  }
  
  protected void createControl() {
   composite = new Composite(parent, SWT.NONE);  
   Composite filler = new Composite(composite, SWT.NONE);
   filler.setSize(0, 10 + topMargin + bottomMargin);
   composite.addPaintListener(this);
   composite.addMouseListener(this);
   composite.addMouseMoveListener(this);
  }
  
  public void setMaximum(int maxValue) {
    this.maxValue = maxValue;
  }
  
  public void setMinimum(int minValue) {
    this.minValue = minValue;
  }
  
  public void setSelection(double selection) {
    double oldSelection = this.selection;
    selection = Math.min(maxValue, Math.max(minValue, selection));
    this.selection = selection;
    double oldPixelPosition = computePixelPosition(oldSelection);
    double newPixelPosition = computePixelPosition(selection);
    composite.redraw((int) Math.min(newPixelPosition, oldPixelPosition), topMargin + 2,
        (int) Math.max(newPixelPosition, oldPixelPosition), 7, false);
    propertyChangeSupport.firePropertyChange("selection", (int) oldSelection, (int) selection);
    System.out.println("selection: " + selection);
  }
  
  protected int computePixelPosition(double selection) { 
    return (int) ((double) (composite.getSize().x) * ((double) selection / (maxValue - minValue)));
  }
  
  public int getSelection() {
    return new BigDecimal(selection + "").setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
  }
  
  public void paintControl(PaintEvent e) {
    
 //   System.out.println("selection: " + selection);
    
  //  System.out.println(composite.getSize().x + " * " + (selection + " / " + maxValue + " - " + minValue));
    
    int pixelPosition = computePixelPosition(selection);
    
 //   System.out.println("pixelPosition: " + pixelPosition);
    
  //  System.out.println("pixelPosition: " + pixelPosition + " : " + (composite.getSize().x - 22));
    
//    if(pixelPosition > composite.getSize().x - 11) {
//      pixelPosition = composite.getSize().x - 11;
//    }
    
    // border
    
    e.gc.setForeground(outlineColor);
    e.gc.drawRectangle(10, topMargin, composite.getSize().x - 20, 10);

    // white background
    
    e.gc.setBackground(new Color(parent.getDisplay(), 255, 255, 255));
    e.gc.fillRectangle(11, topMargin + 1, composite.getSize().x - 21, 9);
    
   // e.gc.setBackground(new Color(parent.getDisplay(), 255, 255, 255));
   // e.gc.fillRectangle(11, 11, 11 +  position, 9);
   
    // filled background
    
    e.gc.setBackground(fillColor);
    e.gc.fillRectangle(12, topMargin + 2, 
        (int) Math.max(0, Math.min(pixelPosition - 12, composite.getSize().x - 23)), 7);
   
  //  e.gc.setBackground(new Color(parent.getDisplay(), 255, 255, 255));
  //  e.gc.fillRectangle(position + 20, 11, 4, 9);
  
  //  e.gc.setForeground(outlineColor);
  //  e.gc.drawRectangle(position + 20, 10, 4, 10);
  }
  
  public void mouseDoubleClick(MouseEvent e) {
    Rectangle rec = new Rectangle(topMargin, 10, composite.getSize().x - 20, 10);
    if(rec.contains(e.x, e.y)) {
      fireMouseDoubleClickEvent(e);
    }
  }
  
  public void mouseDown(MouseEvent e) {
    
  //  Rectangle rec = new Rectangle(topMargin, 10, composite.getSize().x - 20, 10);
    
    mousePressed = true;
    double position = (minValue + maxValue) * ((double) e.x / (composite.getSize().x));
  //  System.out.println(position - 20);
    setSelection(position);
 //   composite.redraw();
    fireMouseDownEvent(e);
  
  }
  
  public void mouseUp(MouseEvent e) {
  //  mouseDown(e);
    mousePressed = false;
    fireMouseUpEvent(e);
  }
  
  public void setLayoutData(Object layoutData) {
    composite.setLayoutData(layoutData);
  }
  
  public void mouseMove(MouseEvent e) {
    
    int x = e.x;
    if(x > composite.getSize().x - 10) {
      x = composite.getSize().x - 10;
    }
    
    if(x < 10) {
      x = 10;
    }
    
    if(mousePressed) {
      double position = (maxValue - minValue) * ((double) x / (composite.getSize().x));
      setSelection(position);
    }
  }
  
  public void addMouseListener(MouseListener me) {
    mouseListeners.add(me);
  }
  
  public void removeMouseListener(MouseListener me) {
    mouseListeners.remove(me);
  }
  
  public Composite getComposite() {
    return composite;
  }
  
  private void fireSelectionEvent() {

  }
  
  private void fireMouseDownEvent(MouseEvent e) {
    for(MouseListener ml : mouseListeners) {
      ml.mouseDown(e);
    }
  }
  
  private void fireMouseUpEvent(MouseEvent e) {
    for(MouseListener ml : mouseListeners) {
      ml.mouseUp(e);
    }
  }
  
  private void fireMouseDoubleClickEvent(MouseEvent e) {
    for(MouseListener ml : mouseListeners) {
      ml.mouseDoubleClick(e);
    }
  }
  
  public static void main(String[] args) {
    Display display = new Display();
    Shell shell = new Shell(display);
    
    shell.setLayout(new FillLayout());
    new SimpleScaleBar(shell, 5, 5);
    
    shell.open();
    shell.layout();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
  }
}
